#![windows_subsystem = "windows"]

use eframe::{egui, App, Frame, NativeOptions };
use egui::{
  ColorImage, Context, Event, FontData, Key, Sense, TextureHandle, Vec2, ViewportBuilder,
  ViewportId
};

use arboard::Clipboard;
use image::{
  DynamicImage, GenericImage, GenericImageView, ImageBuffer, ImageError, Rgba, RgbaImage,
};
use open;
use rfd::FileDialog;
use std::sync::atomic::{AtomicBool, Ordering};
use std::{env, fs, path::PathBuf, sync::Arc};

struct ImageViewer {
  texture: Option<TextureHandle>, // 存储纹理句柄
  show_full: Arc<AtomicBool>,     // 控制是否放大显示
}

// 定义一个新的结构体，用于ImageViewer状态
impl Default for ImageViewer {
  fn default() -> Self {
    Self {
      texture: None,
      show_full: Arc::new(AtomicBool::new(false)),
    }
  }
}

impl ImageViewer {
  // 将 DynamicImage 转换为纹理并更新
  fn update_texture(&mut self, ctx: &Context, image: &DynamicImage, name: &str) {
    if self.texture.is_none() {
      let rgba = image.to_rgba8();
      let size = [rgba.width() as _, rgba.height() as _];
      let binding = rgba.as_flat_samples();
      let pixels = binding.as_slice();
      let color_image = ColorImage::from_rgba_unmultiplied(size, pixels);
      self.texture = Some(ctx.load_texture(name, color_image, Default::default()));
    }
  }

  fn show_fullscreen(&self, ctx: &Context, viewport_id: &str) {
    if self.show_full.load(Ordering::Relaxed) {
      if let Some(texture) = self.texture.clone() {
        let flag = self.show_full.clone();
        ctx.show_viewport_deferred(
          ViewportId::from_hash_of(viewport_id),
          ViewportBuilder::default()
            .with_title("图片")
            .with_inner_size(texture.size_vec2()),
          move |new_ctx, _| {
            egui::CentralPanel::default().show(new_ctx, |ui| {
              ui.image((texture.id(), texture.size_vec2()));
            });
            if new_ctx.input(|i| i.viewport().close_requested()) {
              flag.store(false, Ordering::Relaxed);
            }
          },
        );
      }
    }
  }
}

struct ImageMergerApp {
  first_image: Option<DynamicImage>,
  second_image: Option<DynamicImage>,
  message: String,
  downloads_dir: PathBuf,
  merged_texture: Option<TextureHandle>,
  first_viewer: ImageViewer,  // ✅ 使用 `ImageViewer` 管理第一张图片
  second_viewer: ImageViewer, // ✅ 使用 `ImageViewer` 管理第二张图片
}

impl Default for ImageMergerApp {
  fn default() -> Self {
    Self {
      first_image: None,
      second_image: None,
      message: String::new(),
      downloads_dir: dirs::download_dir().unwrap_or_else(|| env::current_dir().unwrap()),
      merged_texture: None,
      first_viewer: ImageViewer::default(),
      second_viewer: ImageViewer::default(),
    }
  }
}

impl ImageMergerApp {
  fn pick_image(&self) -> Option<DynamicImage> {
    FileDialog::new()
      .add_filter("Image", &["png", "jpg", "jpeg"])
      .pick_file()
      .and_then(|path| image::open(path).ok())
  }

  // 添加一个新的函数，用于从剪贴板读取图片
  fn get_image_from_clipboard(&self) -> Option<DynamicImage> {
    let mut clipboard = Clipboard::new().ok()?;
    let image_data = clipboard.get_image().ok()?;
    println!(
      "读取到剪贴板图片: {}x{}",
      image_data.width, image_data.height
    );
    let img = ImageBuffer::from_raw(
      image_data.width as u32,
      image_data.height as u32,
      image_data.bytes.into_owned(),
    )
    .unwrap();
    Some(DynamicImage::ImageRgba8(img))
  }

  fn fit_size(original: Vec2, max_size: Vec2) -> Vec2 {
    let aspect_ratio = original.x / original.y;
    let mut new_size = original;

    if new_size.x > max_size.x {
      new_size.x = max_size.x;
      new_size.y = new_size.x / aspect_ratio;
    }
    if new_size.y > max_size.y {
      new_size.y = max_size.y;
      new_size.x = new_size.y * aspect_ratio;
    }
    new_size
  }

  // 封装生成唯一文件名的函数
  fn unique_file_name(&self, name: &str, ext: &str) -> PathBuf {
    let mut path = self.downloads_dir.clone();
    path.push(name);
    path.set_extension(ext); // 初始设置扩展名
    let mut i = 1;
    while path.exists() {
      path.set_file_name(format!("{}_{}.{}", name, i, ext));
      i += 1;
    }
    path
  }

  // 清空
  fn clear_images(&mut self) {
    self.first_image.take();
    self.second_image.take();
    self.first_viewer.texture.take();
    self.merged_texture.take();
  }
}

impl App for ImageMergerApp {
  fn update(&mut self, ctx: &egui::Context, _frame: &mut Frame) {
    egui::CentralPanel::default().show(ctx, |ui| {
      
      // 监控 Ctrl+V 按键，读取剪贴板内容
      let events = ctx.input(|i| i.events.clone());
      for event in events {
        if let Event::Key { key, modifiers, .. } = event {
          if key == Key::V && modifiers.command {
            if let Some(img) = self.get_image_from_clipboard() {
              if self.first_image.is_none() {
                self.first_image = Some(img);
              } else if self.second_image.is_none() {
                self.second_image = Some(img);
              }
            }
          }
        }
      }

      // 更新并显示图片
      ui.horizontal(|ui| {
        // 1️⃣ 图片拖拽上传区域
        let drop_target = ui.group(|ui| {
            ui.set_min_height(150.0);
            ui.set_min_width(ui.available_width());
              if self.first_image.is_none() && self.second_image.is_none() {
                // 未加载图片时显示提示信息
                ui.centered_and_justified(|ui| {
                  ui.label("📂 拖放图片到此处\n支持 JPG, PNG, GIF, WEBP 格式\n或使用 Ctrl+V 粘贴图片");
                });
              } else {
                for (label, image, viewer, id) in [
                  ( "第一张图片:", &mut self.first_image, &mut self.first_viewer, "first_image", ),
                  ( "第二张图片:", &mut self.second_image, &mut self.second_viewer, "second_image", ),
                ] {
                  if let Some(img) = image {
                    viewer.update_texture(ctx, img, id);
                    ui.allocate_ui_with_layout(
                      egui::vec2(200.0, 200.0),  // 限制宽度 300，高度 100
                      egui::Layout::top_down(egui::Align::Center),
                      |ui| {
                      if let Some(texture) = &viewer.texture {
                        ui.add_space(15.0);
                        let size = Self::fit_size(texture.size_vec2(), Vec2::new(200.0, 200.0));
                        if ui
                          .add(egui::Image::new((texture.id(), size)).sense(Sense::click()))
                          .clicked() {
                          viewer.show_full.store(true, Ordering::Relaxed);
                        }
                        if ui.button("删除").clicked() {
                          *image = None;
                          viewer.texture = None;
                        }
                      }
                    });
                  } else {
                    ui.label(format!("{} 未选择", label));
                  }
                }
            }

        });

        // if drop_target.clicked() {
          // if let Some(img) = self.pick_image() {
          //   if self.first_image.is_none() {
          //     self.first_image = Some(img);
          //   } else if self.second_image.is_none() {
          //     self.second_image = Some(img);
          //   }
          // }
        // }

        // 检查是否有文件被拖放到窗口
        let dropped_files = ctx.input(|i| i.raw.dropped_files.clone());
        if !dropped_files.is_empty() {
          for file in dropped_files {
            if let Some(path) = file.path {
              // 从文件路径加载图片
              if let Ok(img) = image::open(&path) {
                if self.first_image.is_none() {
                  self.first_image = Some(img);
                } else if self.second_image.is_none() {
                  self.second_image = Some(img);
                }
              } else {
                self.message = format!("无法加载文件: {:?}", path);
              }
            }
          }
        }
        
        for (label, image, viewer, id) in [
          ( "第一张图片:", &mut self.first_image, &mut self.first_viewer, "first_image", ),
          ( "第二张图片:", &mut self.second_image, &mut self.second_viewer, "second_image", ),
        ] {
          if let Some(img) = image {
            viewer.update_texture(ctx, img, id);
            if let Some(texture) = &viewer.texture {
              let size = Self::fit_size(texture.size_vec2(), Vec2::new(200.0, 200.0));
              if ui
                .add(egui::Image::new((texture.id(), size)).sense(Sense::click()))
                .clicked() {
                viewer.show_full.store(true, Ordering::Relaxed);
              }
              if ui.button("删除").clicked() {
                *image = None;
                viewer.texture = None;
              }
            }
          } else {
            ui.label(format!("{} 未选择", label));
          }
        }
      });

      if !self.message.is_empty() {
        ui.label(&self.message);
      }

      ui.add_space(10.0);
      ui.horizontal(|ui| {
        ui.add_space(ui.available_width() * 0.10); // 左边留 25% 空白
        let add_but = ui.add(egui::Button::new("选择图片").min_size(egui::Vec2::new(120.0, 40.0)));
        let save_but = ui.add(egui::Button::new("合并并保存").min_size(egui::Vec2::new(120.0, 40.0)));
        let clear_but = ui.add(egui::Button::new("清空").min_size(egui::Vec2::new(120.0, 40.0)));
        let open_but = ui.add(egui::Button::new("打开保存文件夹").min_size(egui::Vec2::new(120.0, 40.0)));
        // 选择文件
        if add_but.clicked() {
          if let Some(img) = self.pick_image() {
            if self.first_image.is_none() {
              self.first_image = Some(img);
            } else if self.second_image.is_none() {
              self.second_image = Some(img);
            }
          }
        }

        if save_but.clicked() {
          if self.first_image.is_some() && self.second_image.is_some() {
            let output_path = self.unique_file_name("merged_vertical", "png");

            match merge_images_vertically(
              self.first_image.as_ref(),
              self.second_image.as_ref(),
              Some(output_path.to_str().unwrap()),
            ) {
              Ok(Some(_)) => {
                self.message = format!("图片已保存到: {}", output_path.to_str().unwrap());
              }
              Ok(None) => {
                self.message = "保存失败".into();
              }
              Err(e) => {
                self.message = format!("保存失败: {}", e);
              }
            }
          } else {
            self.message = "请先选择两张图片".into();
          }
        }

        if clear_but.clicked() {
          self.clear_images();
        }

        if open_but.clicked() {
          open::that(self.downloads_dir.clone()).unwrap();
        }
        
      });

      // 放大显示第一张图片
      self.first_viewer.show_fullscreen(ctx, "window_1");
      // 放大显示第二张图片
      self.second_viewer.show_fullscreen(ctx, "window_2");
    });
  }
}

// 垂直合并图片
fn merge_images_vertically(
  img1: Option<&DynamicImage>,
  img2: Option<&DynamicImage>,
  output_path: Option<&str>,
) -> Result<Option<DynamicImage>, ImageError> {
  if img1.is_none() || img2.is_none() || output_path.is_none() {
    return Ok(None);
  }

  let img1 = img1.unwrap();
  let img2 = img2.unwrap();

  let (width1, height1) = img1.dimensions();
  let (width2, height2) = img2.dimensions();

  let new_width = width1.max(width2);
  let new_height = height1 + height2;
  let mut new_img: RgbaImage =
    RgbaImage::from_pixel(new_width, new_height, Rgba([255, 255, 255, 255]));

  let img1_x = (new_width - width1) / 2;
  let img2_x = (new_width - width2) / 2;

  new_img.copy_from(&img1.to_rgba8(), img1_x, 0).unwrap();
  new_img
    .copy_from(&img2.to_rgba8(), img2_x, height1)
    .unwrap();

  let result = DynamicImage::ImageRgba8(new_img);
  // output_path
  println!("output_path: {:?}", output_path);
  if let Some(path) = output_path {
    result.save(path)?; // 假设保存成功
  }
  Ok(Some(result))
}

fn setup_custom_fonts(ctx: &egui::Context) {
  // 获取系统字体路径
  let system_root = env::var("SystemRoot").expect("无法获取系统根目录");
  let font_path = format!("{}\\Fonts\\msyh.ttc", system_root); // 字体文件路径

  // 加载字体文件
  let font_data = fs::read(font_path).expect("无法加载字体文件");

  let mut fonts = egui::FontDefinitions::default();
  fonts.font_data.insert(
    "custom".to_owned(),
    // 加载字体数据
    Arc::new(FontData::from_owned(font_data)),
  );

  fonts
    .families
    .entry(egui::FontFamily::Proportional)
    .or_default()
    .insert(0, "custom".to_owned());

  ctx.set_fonts(fonts);
}

fn main() {
  let app = ImageMergerApp::default();
  let native_options = NativeOptions::default();

  eframe::run_native(
    "图片垂直合并工具",
    native_options,
    Box::new(|cc| {
      setup_custom_fonts(&cc.egui_ctx);
      Ok(Box::new(app))
    }),
  )
  .expect("启动失败");
}
